package com.leetcode.lccup;

import java.io.*;
import java.util.*;

/**
 * @author `RKC`
 * @date 2022/4/17 10:54
 */
public class LCCUP5夺回据点 {

    private static final int N = 100010, M = 2 * N, INF = 0x3f3f3f3f;
    private static int[] h = new int[N], e = new int[M], ne = new int[M];
    private static int[] dfn = new int[N], low = new int[N], stk = new int[N];
    private static boolean[] cut = new boolean[N];
    private static Map<Integer, List<Integer>> vdcc = new HashMap<>();
    private static int n, m, idx = 0, timestamp = 0, top = 0, vdccId = 0;

    private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    private static final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));

    public static void main(String[] args) throws IOException {
        String[] ss = reader.readLine().split(" ");
        int n = Integer.parseInt(ss[0]), m = Integer.parseInt(ss[1]);
        int[] cost = new int[n];
        int[][] roads = new int[m][2];
        ss = reader.readLine().split(" ");
        for (int i = 0; i < n; i++) cost[i] = Integer.parseInt(ss[i]);
        for (int i = 0; i < m; i++) {
            ss = reader.readLine().split(" ");
            int a = Integer.parseInt(ss[0]), b = Integer.parseInt(ss[1]);
            roads[i] = new int[]{a, b};
        }
        writer.write(minimumCost(cost, roads) + "\n");
        writer.flush();
    }

    public static long minimumCost(int[] cost, int[][] roads) {
        //需要保留原来的连通性，考虑使用点双连通分量缩点；由于最初只能选择叶子节点，所以对于有k个叶子节点的树，需要选择其中最小的k-1个
        n = cost.length;
        m = roads.length;
        Arrays.fill(h, -1);
        for (int[] road : roads) {
            int a = road[0], b = road[1];
            add(a, b);
            add(b, a);
        }
        //点双连通分量缩点成树，每个点的权值为该双连通分量中非割点权值的最小值
        for (int i = 0; i < n; i++) {
            if (dfn[i] == 0) tarjan(i, i);
        }
        //如果整个图都是一个点双连通分量，选择最小的值
        if (vdcc.size() == 1) {
            int ans = INF;
            for (int i = 0; i < n; i++) ans = Math.min(ans, cost[i]);
            return ans;
        }
        List<Integer> ls = new ArrayList<>();
        //缩点，得到所有叶子节点的权值
        for (int i = 1; i <= vdccId; i++) {
            int cnt = 0, minv = INF;
            for (int v : vdcc.get(i)) {
                if (cut[v]) cnt++;
                else minv = Math.min(minv, cost[v]);
            }
            //该双连通分量只和一个割点相连，是缩点形成的树的叶子节点
            if (cnt == 1) ls.add(minv);
        }
        Collections.sort(ls);
        long ans = 0;
        for (int i = 0; i < ls.size() - 1; i++) ans += ls.get(i);
        return ans;
    }

    private static void tarjan(int u, int root) {
        dfn[u] = low[u] = ++timestamp;
        stk[++top] = u;
        //孤立点
        if (u == root && h[u] == -1) {
            List<Integer> ls = new ArrayList<>(1);
            ls.add(u);
            vdcc.put(++vdccId, ls);
            return;
        }
        int flag = 0;
        for (int i = h[u]; i != -1; i = ne[i]) {
            int v = e[i];
            if (dfn[v] == 0) {
                tarjan(v, root);
                low[u] = Math.min(low[u], low[v]);
                if (low[v] >= dfn[u]) {
                    flag++;
                    if (u != root || flag > 1) cut[u] = true;
                    vdccId++;
                    List<Integer> ls = new ArrayList<>();
                    int t;
                    do {
                        t = stk[top--];
                        ls.add(t);
                    } while (t != v);
                    ls.add(u);
                    vdcc.put(vdccId, ls);
                }
            } else {
                low[u] = Math.min(low[u], dfn[v]);
            }
        }
    }

    private static void add(int a, int b) {
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
    }
}
